package cc.avatar.model;

import java.text.DateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import cc.avatar.model.rule.SaleCommisionPR;

/**
 * 销售单 state = 2时,激活 运输帐务事件 state = 3时,激活 销售人员事件
 * 
 */
@Entity
@Table(name = "t_sale")
public class Sale extends AccountingEvent {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	//首个运货单被创建的时间
	@Temporal(TemporalType.TIMESTAMP)
	private Date createdTime;
	
	@ManyToOne(cascade = { CascadeType.ALL })
	private Party salesPerson;
	
	private String trackingNumber;
	
	private int commisionPrice = 0;

    //双向一对多
	@OneToMany(mappedBy="sale", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
	@OrderBy("id")
	private Set<SaleItem> items = new HashSet<SaleItem>();

	@ManyToOne(cascade = { CascadeType.ALL })
	private Customer customer;

	@Enumerated(EnumType.STRING)
	private SaleState state = SaleState.draft;
  
	@Temporal(TemporalType.TIMESTAMP)
	//状态变为ready_for_payment的时间
	private Date submitTime;
	
	//完成付款的时间
	@Temporal(TemporalType.TIMESTAMP)
	private Date closeTime;

	// when effectivePayment = getReceivablePayment(), the state will be 'close'
	private int effectivePayment;

	//双向一对多
	@OneToMany(mappedBy="sale", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
	private Set<Carriage> carriages = new HashSet<Carriage>();

	// bean properties getter/setter
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Party getSalesPerson() {
		return salesPerson;
	}

	public void setSalesPerson(Party salesPerson) {
		this.salesPerson = salesPerson;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public SaleState getState() {
		return state;
	}

	public void setState(SaleState state) {
		this.state = state;
	}

	public int getEffectivePayment() {
		return effectivePayment;
	}

	public void setEffectivePayment(int effectivePayment) {
		this.effectivePayment = effectivePayment;
	}

	public Set<Carriage> getCarriages() {
		return carriages;
	}

	public Set<SaleItem> getItems() {
		return items;
	}

	public void setItems(Set<SaleItem> items) {
		this.items = items;
	}

	public void setCarriages(Set<Carriage> carriages) {
		this.carriages = carriages;
	}

	public Date getCreatedTime() {
		return createdTime;
	}

	public void setCreatedTime(Date createdTime) {
		this.createdTime = createdTime;
	}

	public Date getSubmitTime() {
		return submitTime;
	}

	public void setSubmitTime(Date submitTime) {
		this.submitTime = submitTime;
	}

	public Date getCloseTime() {
		return closeTime;
	}

	public void setCloseTime(Date closeTime) {
		this.closeTime = closeTime;
	}

	public String getTrackingNumber() {
		return trackingNumber;
	}

	public void setTrackingNumber(String trackingNumber) {
		this.trackingNumber = trackingNumber;
	}

	public void addCarriage(Carriage c){
		assert(c.getId() == null);		
		//建立双向一对多关系
		c.setSale(this);
		if (c.getWhenOccurred() == null)
		    c.setWhenOccurred(new Date());
		this.carriages.add(c);
		//re-calculate sale item
		for (CarriageItem ci : c.getItems()){
			boolean contain = false;
			for (SaleItem si: this.getItems()){
				if (si.getProduct().equals(ci.getProduct())){
					si.setAmount(si.getAmount() + ci.getAmount());
					contain = true;
				    break;
				}
			}
			if (!contain){
				SaleItem si = new SaleItem();
				si.setSale(this);
				si.setProduct(ci.getProduct());
				si.setAmount(ci.getAmount());
				this.getItems().add(si);
			}
		}
	}
	
	@Transient
	//S20100227-01(运送中) 客户名称:xxx  销售员:xx(不提成)
	public String getSummary(){
		StringBuilder s = new StringBuilder();
		String color = null;
		if (this.state == SaleState.draft)
			color = "#CC9900";
		else if (this.state == SaleState.in_transit)
			color = "red";
		else if (this.state == SaleState.prepare_for_payment)
			color = "#00CC33";
		
		if (color != null)
		  s.append("<span style='color:").append(color).append("'>");
		if (this.trackingNumber!=null)
		    s.append(this.trackingNumber).append("&nbsp;&nbsp;");
		s.append("客户:").append(this.getCustomer().getName());				
		s.append("&nbsp;&nbsp;销售员:").append(this.getSalesPerson().getName());		
		s.append("&nbsp;&nbsp;");
		if (this.state == SaleState.in_transit)
		    s.append("运送中");
		else if (this.state == SaleState.prepare_for_payment){
			s.append("待支付(").append("余额:");
			s.append( this.getReceivablePayment() - this.effectivePayment).append(")");
		}else if (this.state == SaleState.draft){
			s.append("草稿(").append(TIMEFORMAT.format(this.createdTime)).append(")");
		} else
			s.append("完成(").append(TIMEFORMAT.format(this.closeTime)).append(")");	
		if (color != null)
		    s.append("</span>");
		return s.toString();
	}
	
	public int getTotalAmount(){
		int sum = 0;
		for (SaleItem item : getItems()) {
			sum += item.getAmount();
		}
		return sum;
	}
	
	@Transient
	// 总销售金额 - 应收款总计
	public int getReceivablePayment() {
		int total = 0;
		for (SaleItem item : getItems()) {
			total += item.getAmount() * item.getPrice();
		}
		return total;
	}
	
	//判断是否全部货款已支付
	public boolean isPaid(){
		if (this.state == SaleState.close)
			return true;
		else 
            return this.effectivePayment == this.getReceivablePayment();
	
	}
	
	@Override
	public Party getStakeholder() {
		return this.salesPerson;
	}

	@Override
	public Date getWhenOccurred() {
		return this.closeTime;
	}
	
	@Override
	protected PostingRule getDefaultRule(){
		return new SaleCommisionPR(this.commisionPrice);
	}
		
	@Override
	public String toString() {
		return this.getTrackingNumber()
	     + " 客户:" + this.getCustomer().getName()
	     + " 总块数:" + getTotalAmount();
	}
	
	public int getCommisionPrice() {
		return commisionPrice;
	}

	public void setCommisionPrice(int commisionPrice) {
		this.commisionPrice = commisionPrice;
	}

	@Transient
	public boolean isReadyForPay(){
		for (SaleItem si:this.items){
			if (si.getPrice() == 0)
				return false;
		}
		return true;
	}
	@Transient
	public final static DateFormat TIMEFORMAT = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	@Override
	public String getAtt1() {
		return this.trackingNumber;
	}

	@Override
	public String getAtt2() {
		return this.customer.getName();
	}

	@Override
	public String getAtt3() {
		return String.valueOf(this.getTotalAmount());
	} 
	
	@Override
	public String getAtt4() {
		return String.valueOf(this.getEffectivePayment());
	} 
}
